package emulator.shell.GUI;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;

public class ConsoleInputStream extends InputStream implements Observer {

	private LinkedList<Byte> buffer = new LinkedList<Byte>();
	
	@Override
	public int read() throws IOException {
		return getFromBuffer();
	}

	@Override
	public void update(Observable observable, Object info) {
		addToBuffer((String) info + "\r\n");
	}

	private synchronized void addToBuffer(String info) {
		byte[] bytes = info.getBytes();
		for (int i = 0; i < bytes.length; i++)
			buffer.addLast(bytes[i]);
		notifyAll();
	}
	
	private synchronized int getFromBuffer() {
		try {
			while (buffer.isEmpty())
				wait();
			int ch = buffer.getFirst();
			buffer.removeFirst();
			return ch;
		} catch (InterruptedException e) {
			return -1;
		}
	}

	/* (non-Javadoc)
	 * @see java.io.InputStream#available()
	 */
	@Override
	public int available() throws IOException {
		return getBufferLength();
	}

	private synchronized int getBufferLength() {
		return buffer.size();
	}

	/* (non-Javadoc)
	 * @see java.io.InputStream#read(byte[], int, int)
	 */
	@Override
	public int read(byte[] b, int off, int len) throws IOException {
		if (len == 0)
			return 0;
		int read_count = internalRead(b, off, len);
		return read_count;
	}

	private synchronized int internalRead(byte[] b, int off, int len) {
		try {
			while (buffer.isEmpty())
				wait();
		} catch (InterruptedException e) {
		}
		int read_count = (len < buffer.size() ? len : buffer.size());
		for (int i = 0; i < read_count; i++)
		{
			b[off+i] = buffer.getFirst();
			buffer.removeFirst();
		}
		return read_count;
	}

}
